<?php

/**
 * Created by PhpStorm.
 * User: xudong.ding
 * Date: 16/5/19
 * Time: 下午2:09
 */
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../../AopSdk.php';



require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/result/AlipayF2FPayResult.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/result/AlipayF2FQueryResult.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/result/AlipayF2FPrecreateResult.php';

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/builder/AopClient.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/builder/SignData.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/builder/AlipayTradePrecreateRequest.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/builder/AlipayTradeQueryContentBuilder.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/builder/AlipayTradeCancelContentBuilder.php';
require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . './../model/builder/AlipayTradeQueryRequest.php';

require_once dirname(__FILE__) . DIRECTORY_SEPARATOR . '../../config.php';

class AlipayTradeService
{

	//支付宝网关地址
	public $gateway_url = "https://openapi.alipay.com/gateway.do";

	//异步通知回调地址
	public $notify_url;

	//签名类型
	public $sign_type;

	//支付宝公钥地址
	public $alipay_public_key;

	//商户私钥地址
	public $private_key;

	//应用id
	public $appid;

	//编码格式
	public $charset = "UTF-8";


	public $token = NULL;

	//重试次数
	private $MaxQueryRetry;

	//重试间隔
	private $QueryDuration;

	//返回数据格式
	public $format = "json";


	function __construct($alipay_config)
	{
		$this->gateway_url = $alipay_config['gatewayUrl'];
		$this->appid = $alipay_config['app_id'];
		$this->sign_type = $alipay_config['sign_type'];
		//$this->private_key = $alipay_config['merchant_private_key_file'];
		$this->private_key = $alipay_config['merchant_private_key'];
		//$this->alipay_public_key = $alipay_config['alipay_public_key_file'];
		$this->alipay_public_key = $alipay_config['alipay_public_key'];
		$this->charset = $alipay_config['charset'];
		$this->MaxQueryRetry = $alipay_config['MaxQueryRetry'];
		$this->QueryDuration = $alipay_config['QueryDuration'];
		$this->notify_url = $alipay_config['notify_url'];

		if (empty($this->appid) || trim($this->appid) == "") {
			throw new Exception("appid should not be NULL!");
		}
		if (empty($this->private_key) || trim($this->private_key) == "") {
			throw new Exception("private_key should not be NULL!");
		}
		if (empty($this->alipay_public_key) || trim($this->alipay_public_key) == "") {
			throw new Exception("alipay_public_key should not be NULL!");
		}
		if (empty($this->charset) || trim($this->charset) == "") {
			throw new Exception("charset should not be NULL!");
		}
		if (empty($this->QueryDuration) || trim($this->QueryDuration) == "") {
			throw new Exception("QueryDuration should not be NULL!");
		}
		if (empty($this->gateway_url) || trim($this->gateway_url) == "") {
			throw new Exception("gateway_url should not be NULL!");
		}
		if (empty($this->MaxQueryRetry) || trim($this->MaxQueryRetry) == "") {
			throw new Exception("MaxQueryRetry should not be NULL!");
		}
		if (empty($this->sign_type) || trim($this->sign_type) == "") {
			throw new Exception("sign_type should not be NULL");
		}
	}
	function AlipayWapPayService($alipay_config)
	{
		$this->__construct($alipay_config);
	}

	// 当面付2.0条码支付(带轮询逻辑)
	public function barPay($req)
	{

		$outTradeNo = $req->getOutTradeNo();
		$bizContent = $req->getBizContent();

		$appAuthToken = $req->getAppAuthToken();

		$this->writeLog($bizContent);

		//echo $bizContent;

		$request = new AlipayTradePayRequest();
		$request->setBizContent($bizContent);


		$response = $this->aopclientRequestExecute($request, NULL, $appAuthToken);

		//获取alipay_trade_pay_response对象数据,方便后续处理
		$response = $response->alipay_trade_pay_response;

		$result = new AlipayF2FPayResult($response);

		if (!empty($response) && ("10000" == $response->code)) {
			// 支付交易明确成功
			$result->setTradeStatus("SUCCESS");
		} elseif (!empty($response) && ("10003" == $response->code)) {
			// 返回用户处理中，则轮询查询交易是否成功，如果查询超时，则调用撤销
			$queryContentBuilder = new AlipayTradeQueryContentBuilder();
			$queryContentBuilder->setOutTradeNo($outTradeNo);
			$queryContentBuilder->setAppAuthToken($appAuthToken);

			$loopQueryResponse = $this->loopQueryResult($queryContentBuilder);
			return $this->checkQueryAndCancel($outTradeNo, $appAuthToken, $result, $loopQueryResponse);
		} elseif ($this->tradeError($response)) {
			// 系统错误或者网络异常未响应，则查询一次交易，如果交易没有支付成功，则调用撤销
			$queryContentBuilder = new AlipayTradeQueryContentBuilder();
			$queryContentBuilder->setOutTradeNo($outTradeNo);
			$queryContentBuilder->setAppAuthToken($appAuthToken);

			$queryResponse = $this->query($queryContentBuilder);

			return $this->checkQueryAndCancel($outTradeNo, $appAuthToken, $result, $queryResponse);
		} else {
			// 其他情况表明该订单支付明确失败
			$result->setTradeStatus("FAILED");
		}

		return $result;
	}

	// 当面付2.0消费查询
	public function queryTradeResult($req)
	{
		$response = $this->query($req);
		$result = new AlipayF2FQueryResult($response);

		if ($this->querySuccess($response)) {
			// 查询返回该订单交易支付成功
			$result->setTradeStatus("SUCCESS");
		} elseif ($this->tradeError($response)) {
			//查询发生异常或无返回，交易状态未知
			$result->setTradeStatus("UNKNOWN");
		} else {
			//其他情况均表明该订单号交易失败
			$result->setTradeStatus("FAILED");
		}
		return $result;
	}

	// 当面付2.0消费退款,$req为对象变量
	public function refund($req)
	{
		$bizContent = $req->getBizContent();
		$this->writeLog($bizContent);
		$request = new AlipayTradeRefundRequest();
		$request->setBizContent($bizContent);
		$response = $this->aopclientRequestExecute($request, NULL, $req->getAppAuthToken());

		$response = $response->alipay_trade_refund_response;

		$result = new AlipayF2FRefundResult($response);
		if (!empty($response) && ("10000" == $response->code)) {
			$result->setTradeStatus("SUCCESS");
		} elseif ($this->tradeError($response)) {
			$result->setTradeStatus("UNKNOWN");
		} else {
			$result->setTradeStatus("FAILED");
		}

		return $result;
	}

	//当面付2.0预下单(生成二维码,带轮询)
	public function qrPay($req)
	{

		$bizContent = $req->getBizContent();
		$this->writeLog($bizContent);

		$request = new AlipayTradePrecreateRequest();
		$request->setBizContent($bizContent);
		$request->setNotifyUrl($this->notify_url);

		// 首先调用支付api
		$response = $this->aopclientRequestExecute($request, NULL, $req->getAppAuthToken());
		$response = $response->alipay_trade_precreate_response;

		$result = new AlipayF2FPrecreateResult($response);
		if (!empty($response) && ("10000" == $response->code)) {
			$result->setTradeStatus("SUCCESS");
		} elseif ($this->tradeError($response)) {
			$result->setTradeStatus("UNKNOWN");
		} else {
			$result->setTradeStatus("FAILED");
		}

		return $result;
	}


	public function query($queryContentBuilder)
	{
		$biz_content = $queryContentBuilder->getBizContent();
		$this->writeLog($biz_content);
		$request = new AlipayTradeQueryRequest();
		$request->setBizContent($biz_content);
		$response = $this->aopclientRequestExecute($request, NULL, $queryContentBuilder->getAppAuthToken());


		return $response->alipay_trade_query_response;
	}

	// 轮询查询订单支付结果
	protected function loopQueryResult($queryContentBuilder)
	{
		$queryResult = NULL;
		for ($i = 1; $i < $this->MaxQueryRetry; $i++) {
			try {
				sleep($this->QueryDuration);
			} catch (Exception $e) {
				print $e->getMessage();
				exit();
			}

			$queryResponse = $this->query($queryContentBuilder);
			if (!empty($queryResponse)) {
				if ($this->stopQuery($queryResponse)) {
					return $queryResponse;
				}
				$queryResult = $queryResponse;
			}
		}
		return $queryResult;
	}

	// 判断是否停止查询
	protected function stopQuery($response)
	{
		if ("10000" == $response->code) {
			if (
				"TRADE_FINISHED" == $response->trade_status ||
				"TRADE_SUCCESS" == $response->trade_status ||
				"TRADE_CLOSED" == $response->trade_status
			) {
				return true;
			}
		}
		return false;
	}

	// 根据查询结果queryResponse判断交易是否支付成功，如果支付成功则更新result并返回，如果不成功则调用撤销
	private function checkQueryAndCancel($outTradeNo, $appAuthToken, $result, $queryResponse)
	{
		if ($this->querySuccess($queryResponse)) {
			// 如果查询返回支付成功，则返回相应结果
			$result->setTradeStatus("SUCCESS");
			$result->setResponse($queryResponse);
			return $result;
		} elseif ($this->queryClose($queryResponse)) {
			// 如果查询返回交易关闭，标记交易失败
			$result->setTradeStatus("FAILED");
			return $result;
		}

		// 如果查询结果不为成功，则调用撤销
		$cancelContentBuilder = new AlipayTradeCancelContentBuilder();
		$cancelContentBuilder->setAppAuthToken($appAuthToken);
		$cancelContentBuilder->setOutTradeNo($outTradeNo);
		$cancelResponse = $this->cancel($cancelContentBuilder);
		if ($this->tradeError($cancelResponse)) {
			// 如果第一次同步撤销返回异常，则标记支付交易为未知状态
			$result->setTradeStatus("UNKNOWN");
		} else {
			// 标记支付为失败，如果撤销未能成功，产生的单边帐由人工处理
			$result->setTradeStatus("FAILED");
		}
		return $result;
	}

	// 查询返回“支付成功”
	protected function querySuccess($queryResponse)
	{
		return !empty($queryResponse) &&
			$queryResponse->code == "10000" && ($queryResponse->trade_status == "TRADE_SUCCESS" ||
				$queryResponse->trade_status == "TRADE_FINISHED");
	}

	// 查询返回“交易关闭”
	protected function queryClose($queryResponse)
	{
		return !empty($queryResponse) &&
			$queryResponse->code == "10000" &&
			$queryResponse->trade_status == "TRADE_CLOSED";
	}

	// 交易异常，或发生系统错误
	protected function tradeError($response)
	{
		return empty($response) ||
			$response->code == "20000";
	}


	public function cancel($cancelContentBuilder)
	{
		$biz_content = $cancelContentBuilder->getBizContent();
		$this->writeLog($biz_content);
		$request = new AlipayTradeCancelRequest();
		$request->setBizContent($biz_content);
		$response = $this->aopclientRequestExecute($request, NULL, $cancelContentBuilder->getAppAuthToken());
		return $response->alipay_trade_cancel_response;
	}

	/**
	 * 使用SDK执行提交页面接口请求
	 * @param unknown $request
	 * @param string $token
	 * @param string $appAuthToken
	 * @return string $$result
	 */
	private function aopclientRequestExecute($request, $token = NULL, $appAuthToken = NULL)
	{

		$aop = new AopClient();
		$aop->gatewayUrl = $this->gateway_url;
		$aop->appId = $this->appid;
		$aop->signType = $this->sign_type;
		//$aop->rsaPrivateKeyFilePath = $this->private_key;
		$aop->rsaPrivateKey = $this->private_key;
		//$aop->alipayPublicKey = $this->alipay_public_key;
		$aop->alipayrsaPublicKey = $this->alipay_public_key;
		$aop->apiVersion = "1.0";
		$aop->postCharset = $this->charset;


		$aop->format = $this->format;
		// 开启页面信息输出
		$aop->debugInfo = true;
		$result = $aop->execute($request, $token, $appAuthToken);

		//打开后，将url形式请求报文写入log文件
		//$this->writeLog("response: ".var_export($result,true));
		return $result;
	}

	function writeLog($text)
	{
		// $text=iconv("GBK", "UTF-8//IGNORE", $text);
		//$text = characet ( $text );
		//file_put_contents("log/log.txt", date("Y-m-d H:i:s") . "  " . $text . "\r\n", FILE_APPEND);
	}

	/** *利用google api生成二维码图片
	 * $content：二维码内容参数
	 * $size：生成二维码的尺寸，宽度和高度的值
	 * $lev：可选参数，纠错等级
	 * $margin：生成的二维码离边框的距离
	 */
	function create_erweima($content, $size = '200', $lev = 'L', $margin = '0')
	{
		$content = urlencode($content);
		$image = '<img src="http://chart.apis.google.com/chart?chs=' . $size . 'x' . $size . '&amp;cht=qr&chld=' . $lev . '|' . $margin . '&amp;chl=' . $content . '"  widht="' . $size . '" height="' . $size . '" />';
		return $image;
	}
}
